using System.Collections.Generic;
using UnityEngine;

namespace ai_library
{
	public class MessageDispatcherException : System.Exception
	{
		protected string message;
		public MessageDispatcherException(string message) { this.message = message; }
		public override string Message { get { return message; } }
		public override string ToString() { return "Message Dispatcher Exception: " + message; }
	}

	public class MessageDispatcher
	{
		private static MessageDispatcher instance = new MessageDispatcher();
		
		private List<Message> m_messages = new List<Message>();

		private MessageDispatcher ()
		{
			CurrentTime = 0.0f;
		}

		public float CurrentTime
		{
			get;
			private set;
		}

		public static MessageDispatcher Instance
		{
			get
			{
				return instance;
			}
		}

		private class MessageSorter : IComparer<Message>
		{
			public int Compare(Message m1, Message m2)
			{
				float value = m1.Delay - m2.Delay;
				
				if (value == 0.0f)
					return 0;
				else
				{
					return value < 0.0f ? 1 : -1;
				}
			}
		}

		public void SendMessage(Message message)
		{
			if (!EntityManager.Instance.IsAgentRegistered(message.ReceiverId))
				throw new MessageDispatcherException("Receiver Agent ID " + message.ReceiverId
				                                     + " not registered with EntityManager");

			if (!EntityManager.Instance.IsAgentRegistered(message.SenderId))
				throw new MessageDispatcherException("Sender Agent ID " + message.SenderId
				                                     + " not registered with EntityManager");

			if (message.Delay > 0.0f)
			{
				m_messages.Add(message);
				m_messages.Sort(new MessageSorter());
			}
		}

		public void Update(float dt)
		{
			CurrentTime += dt;

			for (int i = m_messages.Count - 1; i >= 0; --i)
			{
				Message m = m_messages[i];

				if (m.Delay <= CurrentTime)
				{
					IEntity receiver;
					if (EntityManager.Instance.GetAgentFromKey(m.ReceiverId, out receiver)
					    && receiver != null)
					{
						receiver.ProcessMessage(m);
						m_messages.RemoveAt(i);
					}
					else
					{
						throw new MessageDispatcherException("Couldn't find receiver id " 
						                                     + m.ReceiverId + " in EntityManager");
					}
				}
				else
				{
					break;
				}
			}
		}
	}
}

